#ifndef TERRAIN_GEN_HXX_
#define TERRAIN_GEN_HXX_

#include "../GameObjects/MapNode.hxx"

#include <map>
#include <vector>

struct BiomeData
{
  std::vector<std::string> terrain;            // Terrain IDs
  std::vector<std::string> water;              // Water IDs
  std::vector<std::string> waterDecoration;    // Water Decoration IDs
  std::vector<std::string> waterFloraLight;    // Water Flora Light IDs
  std::vector<std::string> waterFloraMedium;   // Water Flora Medium IDs
  std::vector<std::string> waterFloraDense;    // Water Flora Dense IDs
  std::vector<std::string> terrainRocks;       // Terrain Rocks IDs
  std::vector<std::string> terrainDecoration;  // Terrain Decoration IDs
  std::vector<std::string> terrainFloraLight;  // Terrain Flora (Flowers) Light IDs
  std::vector<std::string> terrainFloraMedium; // Terrain Flora (Flowers) Medium IDs
  std::vector<std::string> terrainFloraDense;  // Terrain Flora (Flowers) Dense IDs
  std::vector<std::string> bushesLight;        // Bushes Light IDs
  std::vector<std::string> bushesMedium;       // Bushes Medium IDs
  std::vector<std::string> bushesDense;        // Bushes Dense IDs
  std::vector<std::string> treesLight;         // Trees Light IDs
  std::vector<std::string> treesMedium;        // Trees Medium IDs
  std::vector<std::string> treesDense;         // Trees Dense IDs
};

struct TerrainSettings
{
  int mapSize = 128;
  int seed = 0;         // If the seed is 0, a random seed will be generated by TerrainGenerator::generateTerrain()
  int seaLevel = 2;     // All tiles with elevation below this will be set as water.
  int treeDensity = 50; // 0% no trees, 100% All trees everywhere all the time.
  int mountainAmplitude =
      10;              // Both amplifies the mountain noise source, as well as biasing the mountain/plains blend. Expects 0-100.
  int waterAmount = 5; // Density of freshwater in addition to coastlines and rivers. Expects 0-100.
  int coasts =
      1; // 4 least significant bits are bitmasked, where 0 is a land border and 1 is a coastline. Remaining bits reserved for future use.
  int rivers = 1;              // Number of rivers to attempt generating.
  std::string biomes = "{}";   // JSON string of biomes to attempt using, plus any options associated with them.
  std::string advanced = "{}"; // JSON string of arbitrary advanced option data for future use or mods.
};

class TerrainGenerator
{
public:
  TerrainGenerator() = default;
  ~TerrainGenerator() = default;

  void generateTerrain(std::vector<MapNode> &mapNodes, std::vector<MapNode *> &mapNodesInDrawingOrder);

  void loadTerrainDataFromJSON();

private:
  TerrainSettings m_terrainSettings;

  std::map<std::string, BiomeData> m_biomeInformation; // key: biome
};

#endif
